package main

import (
	"context"
	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
	"log"
)

type config struct {
	v *viper.Viper
}

func LoadConfigFromYaml(c *config) error {
	c.v = viper.New()

	// 设置配置文件的名字
	c.v.SetConfigName("config")

	//添加配置文件所在的路径,注意在Linux环境下%GOPATH要替换为$GOPATH
	//  注意：如果不用AddConfigPath去指定路径，它会在程序执行的目录去寻找config.yaml
	c.v.AddConfigPath("$GOPATH/src/")
	c.v.AddConfigPath("./")
	//设置配置文件类型
	c.v.SetConfigType("yaml")
	if err := c.v.ReadInConfig(); err != nil {
		return err
	}
	log.Printf("age: %s, name: %s \n", c.v.Get("information.age"), c.v.Get("information.name"))
	return nil
}

//监听配置文件
//监听配置文件的修改和变动
// 重点来了啊，这个可以说是非常非常实用的一个功能，以往我们修改配置文件要么重启服务，要么搞一个api去修改，
// Viper把这个功能帮我们实现了。只要配置文件被修改保存后，我们事先注册的watch函数就回被触发，只要我们在这里面添加更新操作就ok了。不过美中不足的是，它目前只监听配置文件。
func WatchConfig(c *config) error {
	if err := LoadConfigFromYaml(c); err != nil {
		return err
	}
	ctx, cancel := context.WithCancel(context.Background())
	c.v.WatchConfig()
	//监听回调函数
	watch := func(e fsnotify.Event) {
		log.Printf("Config file is changed: %s \n", e.String())
		cancel()
	}
	c.v.OnConfigChange(watch)
	<-ctx.Done()
	return nil
}

func main() {
	var c config
	for {
		err := WatchConfig(&c)
		if err != nil {
			panic(err)
		}
	}
}
